/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001-2006 by:
EXSE, Department of Geography, University of Bonn
http://www.giub.uni-bonn.de/deegree/
lat/lon GmbH
http://www.lat-lon.de
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact :
Andreas Poth
lat/lon GmbH
Aennchenstr. 19
53177 Bonn
Germany
E-Mail: poth@lat-lon.de
Prof. Dr. Klaus Greve
Department of Geography
University of Bonn
Meckenheimer Allee 166
53115 Bonn
Germany
E-Mail: greve@giub.uni-bonn.de
---------------------------------------------------------------------------*/
package org.deegree.model.spatialschema;
import java.io.Serializable;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.log.LoggerFactory;
import org.deegree.model.crs.CoordinateSystem;
/**
* Default implementation of the Geometry interface from package deegree.model. The implementation
* is abstract because only the management of the spatial reference system is unique for all
* geometries.
* <p>
*
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
* @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider</a>
* @version $Revision: 1.16 $ $Date: 2006/11/27 09:07:51 $
*/
public abstract class GeometryImpl implements Geometry, Serializable {
private static final ILogger LOG = LoggerFactory.getLogger( GeometryImpl.class );
/** Use serialVersionUID for interoperability. */
private final static long serialVersionUID = 130728662284673112L;
protected static double mute = 0.000000001;
protected CoordinateSystem crs = null;
protected Boundary boundary = null;
protected Envelope envelope = null;
protected Geometry convexHull = null;
protected Point centroid = null;
protected boolean empty = true;
protected boolean valid = false;
/**
* constructor that sets the spatial reference system
*
* @param crs
* new spatial reference system
*/
protected GeometryImpl( CoordinateSystem crs ) {
setCoordinateSystem( crs );
}
/**
* @return the spatial reference system of a geometry
*/
public CoordinateSystem getCoordinateSystem() {
return crs;
}
/**
* sets the spatial reference system
*
* @param crs
* new spatial reference system
*/
public void setCoordinateSystem( CoordinateSystem crs ) {
this.crs = crs;
}
/**
* @return a shallow copy of the geometry. this isn't realized at this level so a
* CloneNotSupportedException will be thrown.
*/
@Override
public Object clone()
throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
/**
* @return true if no geometry values resp. points stored within the geometry.
*/
public boolean isEmpty() {
return empty;
}
/**
*
* @param empty
* indicates the geometry as empty
*/
public void setEmpty( boolean empty ) {
this.empty = empty;
}
/**
* returns the boundary of the surface as general boundary
*
*/
public Boundary getBoundary() {
if ( !isValid() ) {
calculateParam();
}
return boundary;
}
/**
* dummy implementation of this method
*/
public void translate( double[] d ) {
setValid( false );
}
/**
* <p>
* The operation "distance" shall return the distance between this Geometry and another
* Geometry. This distance is defined to be the greatest lower bound of the set of distances
* between all pairs of points that include one each from each of the two Geometries. A
* "distance" value shall be a positive number associated to distance units such as meters or
* standard foot. If necessary, the second geometric object shall be transformed into the same
* coordinate reference system as the first before the distance is calculated.
* </p>
* <p>
* If the geometric objects overlap, or touch, then their distance apart shall be zero. Some
* current implementations use a "negative" distance for such cases, but the approach is neither
* consistent between implementations, nor theoretically viable.
* </p>
*/
public double distance( Geometry gmo ) {
try {
com.vividsolutions.jts.geom.Geometry jtsThis = JTSAdapter.export( this );
com.vividsolutions.jts.geom.Geometry jtsThat = JTSAdapter.export( gmo );
return jtsThis.distance( jtsThat );
} catch ( GeometryException e ) {
LOG.logError( e.getMessage(), e );
return -1;
}
}
/**
* <p>
* The operation "centroid" shall return the mathematical centroid for this Geometry. The result
* is not guaranteed to be on the object. For heterogeneous collections of primitives, the
* centroid only takes into account those of the largest dimension. For example, when
* calculating the centroid of surfaces, an average is taken weighted by area. Since curves have
* no area they do not contribute to the average.
* </p>
*/
public Point getCentroid() {
if ( !isValid() ) {
calculateParam();
}
return centroid;
}
/**
* returns the bounding box / envelope of a geometry
*/
public Envelope getEnvelope() {
if ( !isValid() ) {
calculateParam();
}
return envelope;
}
/**
* <p>
* The operation "convexHull" shall return a Geometry that represents the convex hull of this
* Geometry.
* </p>
* This method throws an @see java.lang.UnsupportedOperationException an may has an
* useful implementation in extending classes
*/
public Geometry getConvexHull() {
throw new UnsupportedOperationException();
}
/**
* <p>
* The operation "buffer" shall return a Geometry containing all points whose distance from this
* Geometry is less than or equal to the "distance" passed as a parameter. The Geometry returned
* is in the same reference system as this original Geometry. The dimension of the returned
* Geometry is normally the same as the coordinate dimension - a collection of Surfaces in 2D
* space and a collection of Solids in 3D space, but this may be application defined.
* </p>
* This method throws an @see java.lang.UnsupportedOperationException an may has an
* useful implementation in extending classes
*/
public Geometry getBuffer( double distance ) {
throw new UnsupportedOperationException();
}
/**
* The Boolean valued operation "contains" shall return TRUE if this Geometry contains another
* Geometry.
* <p>
*
* @param that
* the Geometry to test (whether is is contained)
* @return true if the given object is contained, else false
*/
public boolean contains( Geometry that ) {
try {
// let JTS do the hard work
com.vividsolutions.jts.geom.Geometry jtsThis = JTSAdapter.export( this );
com.vividsolutions.jts.geom.Geometry jtsThat = JTSAdapter.export( that );
return jtsThis.contains( jtsThat );
} catch ( GeometryException e ) {
LOG.logError( e.getMessage(), e );
return false;
}
}
/**
* The Boolean valued operation "contains" shall return TRUE if this Geometry contains a single
* point given by a coordinate.
*
* @param position
* Position to test (whether is is contained)
* @return true if the given object is contained, else false
*/
public boolean contains( Position position ) {
return contains( new PointImpl( position, null ) );
}
/**
* The Boolean valued operation "intersects" shall return TRUE if this Geometry intersects
* another Geometry. Within a Complex, the Primitives do not intersect one another. In general,
* topologically structured data uses shared geometric objects to capture intersection
* information.
*
* @param that
* the Geometry to intersect with
* @return true if the objects intersects, else false
*/
public boolean intersects( Geometry that ) {
try {
// let JTS do the hard work
com.vividsolutions.jts.geom.Geometry jtsThis = JTSAdapter.export( this );
com.vividsolutions.jts.geom.Geometry jtsThat = JTSAdapter.export( that );
return jtsThis.intersects( jtsThat );
} catch ( GeometryException e ) {
LOG.logError( "", e );
return false;
}
}
/**
* The "union" operation shall return the set theoretic union of this Geometry and the passed
* Geometry.
*
* @param that
* the Geometry to unify
* @return intersection or null, if computation failed
*/
public Geometry union( Geometry that ) {
Geometry union = null;
try {
// let JTS do the hard work
com.vividsolutions.jts.geom.Geometry jtsThis = JTSAdapter.export( this );
com.vividsolutions.jts.geom.Geometry jtsThat = JTSAdapter.export( that );
com.vividsolutions.jts.geom.Geometry jtsUnion = jtsThis.union( jtsThat );
if ( !jtsUnion.isEmpty() ) {
union = JTSAdapter.wrap( jtsUnion );
( (GeometryImpl) union ).setCoordinateSystem( getCoordinateSystem() );
}
} catch ( GeometryException e ) {
LOG.logError( e.getLocalizedMessage(), e );
}
return union;
}
/**
* The "intersection" operation shall return the set theoretic intersection of this
* <tt>Geometry</tt> and the passed <tt>Geometry</tt>.
*
* @param that
* the Geometry to intersect with
* @return intersection or null, if it is empty (or computation failed)
*/
public Geometry intersection( Geometry that )
throws GeometryException {
Geometry intersection = null;
// let JTS do the hard work
com.vividsolutions.jts.geom.Geometry jtsIntersection = null;
try{
com.vividsolutions.jts.geom.Geometry jtsThis = JTSAdapter.export( this );
com.vividsolutions.jts.geom.Geometry jtsThat = JTSAdapter.export( that );
jtsIntersection = jtsThis.intersection( jtsThat );
}
catch (Exception e ){
throw new GeometryException( e.getLocalizedMessage() );
}
if ( jtsIntersection != null && !jtsIntersection.isEmpty() ) {
intersection = JTSAdapter.wrap( jtsIntersection );
( (GeometryImpl) intersection ).setCoordinateSystem( getCoordinateSystem() );
}
return intersection;
}
/**
* The "difference" operation shall return the set theoretic difference of this Geometry and the
* passed Geometry.
*
* @param that
* the Geometry to calculate the difference with
* @return difference or null, if it is empty (or computation failed)
*/
public Geometry difference( Geometry that ) {
Geometry difference = null;
try {
// let JTS do the hard work
com.vividsolutions.jts.geom.Geometry jtsThis = JTSAdapter.export( this );
com.vividsolutions.jts.geom.Geometry jtsThat = JTSAdapter.export( that );
com.vividsolutions.jts.geom.Geometry jtsDifference = jtsThis.difference( jtsThat );
if ( !jtsDifference.isEmpty() ) {
difference = JTSAdapter.wrap( jtsDifference );
( (GeometryImpl) difference ).setCoordinateSystem( getCoordinateSystem() );
}
} catch ( GeometryException e ) {
LOG.logError( "", e );
}
return difference;
}
/**
* Compares the Geometry to be equal to another Geometry.
*
* @param that
* the Geometry to test for equality
* @return true if the objects are equal, else false
*/
@Override
public boolean equals( Object that ) {
if ( ( that == null ) || !( that instanceof GeometryImpl ) ) {
return false;
}
if ( crs != null ) {
if ( !crs.equals( ( (Geometry) that ).getCoordinateSystem() ) ) {
return false;
}
} else {
if ( ( (Geometry) that ).getCoordinateSystem() != null ) {
return false;
}
}
// do not add JTS calls here!!!!
return true;
}
/**
* provide optimized proximity queries within for a distance . calvin added on 10/21/2003
*/
public boolean isWithinDistance( Geometry that, double distance ) {
if ( that == null )
return false;
try {
// let JTS do the hard work
com.vividsolutions.jts.geom.Geometry jtsThis = JTSAdapter.export( this );
com.vividsolutions.jts.geom.Geometry jtsThat = JTSAdapter.export( that );
return jtsThis.isWithinDistance( jtsThat, distance );
} catch ( GeometryException e ) {
LOG.logError( e.getMessage(), e );
return false;
}
}
public void setTolerance(double tolerance) {
mute = tolerance;
}
/**
*
* @param valid
* invalidates the calculated parameters of the Geometry
*/
protected void setValid( boolean valid ) {
this.valid = valid;
}
/**
* @return true if the calculated parameters of the Geometry are valid and false if they must be
* recalculated
*/
protected boolean isValid() {
return valid;
}
/**
* recalculates internal parameters
*/
protected abstract void calculateParam();
/**
*
* @return the String representation containing the crs, empty-field and the mut-field
*/
@Override
public String toString() {
String ret = null;
ret = "CoordinateSystem = " + crs + "\n";
ret += ( "empty = " + empty + "\n" );
ret += ( "mute = " + mute + "\n" );
return ret;
}
}
/* *************************************************************************************************
* Changes to this class. What the people have been up to:
* $Log: GeometryImpl.java,v $
* Revision 1.16 2006/11/27 09:07:51 poth
* JNI integration of proj4 has been removed. The CRS functionality now will be done by native deegree code.
*
* Revision 1.15 2006/10/17 08:14:23 poth
* getBuffer now throws UnsupportedOperationException
*
* Revision 1.14 2006/10/02 07:31:34 bezema
* added a try clause over the merge section.
* Changes to this class. What the people have been up to:
* Revision 1.13 2006/09/14 08:44:39 poth
* *** empty log message ***
* Changes to this class. What the people have been up to:
* Revision 1.12 2006/08/28 07:50:11 bezema
* Added isNan support for the 3 dimension
* Revision 1.11
* 2006/07/04 18:32:09 poth code formatation
*
*
************************************************************************************************ */